package com.black.utils.network.transmit.udp;

import com.black.utils.commons.network.ServerThread;
import lombok.extern.slf4j.Slf4j;

import java.io.Closeable;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;

/**
 * @author ylx
 */
@Slf4j
public class UDPServer implements Closeable {
    private final DatagramSocket socket;
    private static final int MAX_LEN = 1024;
    private static final byte[] BUFFER = new byte[MAX_LEN];

    public UDPServer(int port) throws SocketException {
        socket = new DatagramSocket(port);
        new UDPServerThread().start();
    }

    @Override
    public void close() {
        socket.close();
    }

    private class UDPServerThread extends ServerThread {
        private DatagramPacket request;

        @Override
        public void run() {
            String simpleName = this.getClass().getSimpleName();
            while (!socket.isClosed()) {
                synchronized (socket) {
                    try {
                        request = new DatagramPacket(BUFFER, BUFFER.length);
                        String message = receive();
                        String responseMsg = handle(message);
                        response(responseMsg);
                    } catch (Exception e) {
                        log.error("server: {}; socket error: {}", simpleName, e.getMessage());
                    }
                }
            }
            log.info("server: {}; socket closed", simpleName);
        }

        @Override
        protected String receiveMsg() throws IOException {
            socket.receive(request);
            String message = new String(request.getData(), 0, request.getLength());
            log.info("receive message: {} ; start new thread to deal", message);
            return message;
        }

        @Override
        protected void responseMsg(String response) throws Exception {
            byte[] buffer = response.getBytes();
            DatagramPacket responsePacket = new DatagramPacket(buffer, buffer.length, request.getAddress(), request.getPort());
            socket.send(responsePacket);
        }
    }
}
